<?php

namespace App\Miya\UIData;

use App\Miya\Models\Debris;
use App\Miya\Models\Info;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class DebrisData extends CommonData
{
    protected $name = 'debris';
    protected $infoFields = [
        'id', 'module_id', 'classify_id', 'name', 'keyword_id', 'avatar',
        'content', 'tag', 'images', 'is_delayed', 'delayed_at',
        'custom_keywords', 'page_views', 'extends', 'created_at'
    ];

    /**
     * 通过碎片id获取信息
     * @param $id 碎片id
     * @param $hash 模块属性hash
     *
     * @operate 遍历后调用
     *
     * @data id 信息id
     * @data module 对应模块信息 id:模块id tag:模块标签 name:模块名称
     * @data classify 对应分类信息 id:分类id tag:分类标签 name:分类名称
     * @data name 信息名称
     * @data keyword 关键词信息 id:关键词id keyword:关键词
     * @data keywords 关键词字符串
     * @data avatar 信息封面度
     * @data content 信息内容
     * @data tag 信息标签
     * @data images 信息图片列表
     * @data custom_keywords 信息自定义关键词
     * @data extends 拓展信息列表 单个调用建议使用array_get
     * @data page_views 访问量
     * @data type_list 属性信息列表
     * @data time 信息时间
     * @data url() 信息超链接
     * @data sketch() 信息内容的部分简略信息 默认100
     * @data parseTime('Y-m-d H:i:s') 格式化信息时间
     */
    public function get($id, $hash = null): Collection
    {
        return $this->dataCache(function () use ($id, $hash) {
            $debris = Debris::find($id);

            if (!$debris) {
                $msg = sprintf('碎片中未找到id为 %s 的数据信息', $id);
                throw new ModelNotFoundException($msg);
            }

            return $this->parseData($debris, $hash);
        }, __METHOD__, $id);
    }

    /**
     * 通过碎片tag获取信息
     * @param $tag 碎片Tag
     * @param $hash 模块属性hash
     *
     * @operate 遍历后调用
     *
     * @data id 信息id
     * @data module 对应模块信息 id:模块id tag:模块标签 name:模块名称
     * @data classify 对应分类信息 id:分类id tag:分类标签 name:分类名称
     * @data name 信息名称
     * @data keyword 分类关键词信息 id:关键词id keyword:关键词
     * @data avatar 信息封面度
     * @data content 信息内容
     * @data tag 信息标签
     * @data images 信息图片列表
     * @data custom_keywords 信息自定义关键词
     * @data extends 拓展信息列表 单个调用建议使用array_get
     * @data page_views 访问量
     * @data type_list 属性信息列表
     * @data time 信息时间
     * @data url() 信息超链接
     * @data sketch() 信息内容的部分简略信息 默认100
     * @data parseTime('Y-m-d H:i:s') 格式化信息时间
     */
    public function getByTag($tag, $hash = null): Collection
    {
        return $this->dataCache(function () use ($tag, $hash) {
            $debris = Debris::whereTag($tag)->first();

            if (!$debris) {
                $msg = sprintf('碎片中未找到tag为 %s 的数据信息', $tag);
                throw new ModelNotFoundException($msg);
            }

            return $this->parseData($debris, $hash);
        }, __METHOD__, $tag);
    }

    /**
     * 获取信息数据
     * @param Debris $debris
     * @return mixed
     */
    protected function parseData(Debris $debris, $hash): Collection
    {
        $builder = Info::select($this->infoFields)
            ->with(Info::$DefaultRelationships)
            ->where('status', 1)
            ->where('module_id', $debris->module_id)
            ->where(function ($query) {
                $query->where('is_delayed', 2)->orWhere(function ($query) {
                    $query->where('is_delayed', 1)->where('delayed_at', '<=', now());
                });
            })->where(function ($query) use ($debris) {
                //选择分类,包含子分类
                if ($debris->classifies) {
                    $query->whereIn('classify_id', $debris->classifies_with_descendants);
                }
            })->where(function ($query) use ($hash) {
                if ($hash) {
                    $query->whereHas('types', function ($query) use ($hash) {
                        $query->where('value', $hash);
                    });
                }
            });

        //信息排序
        $builder = Info::rankByType($builder, $debris->rank_type);

        $infos = $builder->take($debris->num)->get();
        $infos = $infos->map(function ($info) {
            $info->avatar && $info->avatar = asset('uploads/' . $info->avatar);
            $info->images = array_map(function ($img) {
                return asset('uploads/' . $img);
            }, $info->images);
            $info->keywords = $info->getKeywords();
            return $info;
        });

        return $infos;
    }
}
